package com.jmb.api.web.core.http;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jmb.api.common.utils.InterfaceConstants;
import com.jmb.api.entity.HttpSetting;
import com.jmb.api.web.mapper.HttpSettingMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.ssl.SSLContexts;
import org.apache.hc.core5.ssl.TrustStrategy;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URISyntaxException;
import java.security.KeyStore;
import java.util.List;

import static com.jmb.api.common.utils.InterfaceConstants.*;

@Slf4j
@Component
public class RequestFactory {
    @Autowired
    private HttpSettingMapper httpSettingMapper;

    /**
     * 支持http https 底层基于HttpsURLConnection
     * @return SimpleClientHttpRequestFactory
     */
     public SimpleClientHttpRequestFactory byURLConnection() {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(){
            @Override

            protected void prepareConnection(HttpURLConnection connection, String httpMethod) {
                try {
                    // 检查传入的connection对象是否为HttpURLConnection类型
                    if (connection instanceof HttpURLConnection){
                        KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
                        // 信任任何连接，授权所有ssl证书
                        TrustStrategy trustStrategy = (x509Certificates, s) -> true;
                        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(store, trustStrategy).build();
                        ((HttpsURLConnection) connection).setSSLSocketFactory(sslContext.getSocketFactory());
                        HttpsURLConnection httpsConnection = (HttpsURLConnection) connection;
                        super.prepareConnection(httpsConnection, httpMethod);
                    }else {
                        super.prepareConnection(connection, httpMethod);
                    }
                }catch (Exception e){
                    log.error("创建请求失败：{}", String.valueOf(e));
                }
            }
        };
         Proxy proxy = proxy4HttpUrlConnection();
         if (proxy != null){
             factory.setProxy(proxy);
         }
         factory.setConnectTimeout(connectTimeout());
         factory.setReadTimeout(readTimeout());
         return factory;
    }

    /**
     * 支持http https 底层基于HttpClient
     * @return HttpComponentsClientHttpRequestFactory
     */
    public HttpComponentsClientHttpRequestFactory byHttpClient() {
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
        try {
           SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, (x509Certificates, s) -> true).build();
        } catch (Exception e) {
            log.error("创建请求失败：{}", String.valueOf(e));
        }
        HttpClientBuilder builder = HttpClients.custom();
        builder.setProxy(proxy4HttpClient());
        CloseableHttpClient closeableHttpClient = builder.build();
        factory.setHttpClient(closeableHttpClient);
        factory.setConnectTimeout(connectTimeout());
        return factory;
    }

    // 创建连接
    private HttpHost proxy4HttpClient( ) {
        HttpSetting proxyHttpSetting = getProxyHttpSetting();
        if (proxyHttpSetting != null){
            try {
                return HttpHost.create(proxyHttpSetting.getValue());
            } catch (URISyntaxException e) {
                log.error("代理配置项值错误：{}", String.valueOf(e));
                return null;
            }
        }
        return null;
    }

    // 获取代理
    private Proxy proxy4HttpUrlConnection() {
        HttpSetting proxy = getProxyHttpSetting();
        if (proxy != null){
            // 获取配置项值
            String value = proxy.getValue();
            if (value == null || value.isEmpty()){
                return null;
            }
            // 获取代理proxy
            String[] domain = value.split(":");
            if (domain.length != 2){
                return null;
            }
            try {
                String host = domain[0];
                int prot = Integer.parseInt(domain[1]);
                return new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, prot));
            }catch (NumberFormatException e){
                log.error("代理配置项值错误：{}", String.valueOf(e));
                return null;
            }
        }
        return null;
    }



    // 提取的公共方法，获取Http settings

    private HttpSetting getProxyHttpSetting() {
        LambdaQueryWrapper<HttpSetting> httpSettingWrapper = new LambdaQueryWrapper<>();
        httpSettingWrapper.eq(HttpSetting::getStatus, 0)
                .eq(HttpSetting::getType, InterfaceConstants.PROXY_TYPE);
        List<HttpSetting> httpSettingList = httpSettingMapper.selectList(httpSettingWrapper);

        return httpSettingList.isEmpty()?null: httpSettingList.get(0);
    }

    /**
     * 获取connectTimeout超时时常单位秒
     * @return 秒
     */
    private Integer connectTimeout() {
        return getTimeout(CONNECT_TIMEOUT_TYPE, DEFAULT_CONNECT_TIMEOUT);
    }

    /**
     * 获取ReadTimeout超时时常单位秒
     * @return 秒
     */
    private Integer readTimeout() {
        return getTimeout(READ_TIMEOUT_TYPE, DEFAULT_READ_TIMEOUT);
    }
    // 获取超时时间

    private Integer getTimeout(Integer type,Integer defaultTimeout){
        LambdaQueryWrapper<HttpSetting> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(HttpSetting::getStatus, 0).eq(HttpSetting::getType, type);
        List<HttpSetting> httpSettingList = httpSettingMapper.selectList(queryWrapper);
        if (httpSettingList.isEmpty()){
            String value = httpSettingList.get(0).getValue();
            int timeout = Integer.parseInt(value);
            return timeout<0? defaultTimeout:timeout;
        }
        return defaultTimeout;
    }


}
